package com.freedom.monitor.myeye.client.reap;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.freedom.monitor.myeye.client.queue.DataQueue;
import com.freedom.monitor.myeye.client.upload.UploadRunnable;
import com.freedom.monitor.myeye.client.utils.Logger;
import com.freedom.monitor.myeye.client.utils.PropertyUtils;
import com.freedom.monitor.myeye.commmon.utils.StringUtils;

public class ReapMap {
	//
	private static Logger logger = Logger.getLogger(ReapMap.class);
	//
	private static final Object OBJECT = new Object();
	private static final List<Object> OBJECT_HOLDERS = new ArrayList<Object>();
	private static final String REAP_PERIOD = "reapPeriod";
	private static final String QUEUE_SIZE = "queueSize";
	//
	//
	//
	// 这里，我们选择 HashMap来做容器
	// 不可以用带锁的，锁的其它处理保证会在下面来做
	// 目的还是为了性能
	private static HashMap<String, Object> MAP = new HashMap<String, Object>();

	public static void handle(String product, String service) {
		// 1)check whether exist
		String key = StringUtils.unionByMagicKey(product, service);
		if (null == MAP.get(key)) {// 正常情况下，不会出现,所以刚开始会出现，后面不会的
			synchronized (ReapMap.class) {
				if (null == MAP.get(key)) {// double check
					// 开启新的收割线程
					startQueuePlusThreads(product, service);
					// 放置存在标记
					MAP.put(key, OBJECT);
					logger.info("start all threads and queue for product--->[" + product + "] service--->[" + service
							+ "]");
				}
			}
		}
	}

	// scheduleAtFixedRate 与 scheduleWithFixedDelay 的区别请参考下面的代码
	// http://blog.csdn.net/u013819945/article/details/47723091
	private static void startQueuePlusThreads(String product, String service) {
		// 1)增加队列
		DataQueue.initQueue(StringUtils.unionByMagicKey(product, service),
				Integer.parseInt(PropertyUtils.getInstance().getProperty(QUEUE_SIZE)));
		// 2)增加采样线程,这个方法保证不会并发执行
		/**
		 * 关于scheduleAtFixedRate的说明 // Creates and executes a periodic action
		 * that becomes enabled first after the given initial delay, and
		 * subsequently with the given period; that is executions will commence
		 * after initialDelay then initialDelay+period, then initialDelay + 2 *
		 * period, and so on. If any execution of the task encounters an
		 * exception, subsequent executions are suppressed. Otherwise, the task
		 * will only terminate via cancellation or termination of the executor.
		 * If any execution of this task takes longer than its period, then
		 * subsequent executions may start late, but will not concurrently
		 * execute.
		 * 
		 * 
		 */
		{
			Runnable reapRunnable = new MyReapRunnable(product, service);
			int reapPeriod = Integer.parseInt(PropertyUtils.getInstance().getProperty(REAP_PERIOD));
			ScheduledExecutorService reapScheduler = Executors.newSingleThreadScheduledExecutor();
			reapScheduler.scheduleAtFixedRate(reapRunnable, reapPeriod, reapPeriod, TimeUnit.SECONDS);
			OBJECT_HOLDERS.add(reapScheduler);
		}
		// 3)增加上报线程(10毫秒执行1次),这个方法保证不会并发执行

		{
			Runnable uploadRunnable = new UploadRunnable(product, service);
			ScheduledExecutorService uploadScheduler = Executors.newSingleThreadScheduledExecutor();
			uploadScheduler.scheduleAtFixedRate(uploadRunnable, 0, 10, TimeUnit.MILLISECONDS);// 毫秒，这个不由用户自己定义
			OBJECT_HOLDERS.add(uploadScheduler);
		}
		//
	}
}
